﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Diagnostics;

namespace TfsGiggle.Core
{
    /// <summary>
    /// Changeset
    /// </summary>
    [Serializable]
    public struct TfsGiggleChangeset : IEqualityComparer<TfsGiggleChangeset>
    {
        /// <summary>
        /// Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// Committer
        /// </summary>
        public string Committer { get; set; }

        /// <summary>
        /// Comment
        /// </summary>
        public string Comment { get; set; }

        /// <summary>
        /// TeamProjectCollectionId
        /// </summary>
        public string TeamProjectCollectionId;

        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Equals(TfsGiggleChangeset x, TfsGiggleChangeset y)
        {
            Trace.TraceInformation("Equals called");
            return x.Id == y.Id && x.TeamProjectCollectionId == y.TeamProjectCollectionId;
        }

        /// <summary>
        /// Hashcode
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int GetHashCode(TfsGiggleChangeset obj)
        {
            unchecked
            {
                Trace.TraceInformation("GetHashCode called");
                return obj.TeamProjectCollectionId.GetHashCode() * 31 + obj.Id.GetHashCode();
            }
        }

        /// <summary>
        /// Hashcode
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            unchecked
            {
                Trace.TraceInformation("GetHashCode called");
                return this.GetHashCode(this);
            }
        }

        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static bool operator ==(TfsGiggleChangeset x, TfsGiggleChangeset y)
        {
            Trace.TraceInformation("== called");
            return x.Equals(y);
        }

        /// <summary>
        /// Not equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static bool operator !=(TfsGiggleChangeset x, TfsGiggleChangeset y)
        {
            Trace.TraceInformation("!= called");
            return !x.Equals(y);
        }

        /// <summary>
        /// Equals again
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            Trace.TraceInformation("Equals called");
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            var tfsGiggleChangeset = (TfsGiggleChangeset)obj;
            if (tfsGiggleChangeset.Id == Id && tfsGiggleChangeset.TeamProjectCollectionId == TeamProjectCollectionId)
            {
                return true;
            }
            return false;
        }
    }

    /// <summary>
    /// Workitem
    /// </summary>
    [Serializable]
    public struct TfsGiggleWorkitem : IEqualityComparer<TfsGiggleWorkitem>
    {
        /// <summary>
        /// Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// Title
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// TeamProjectCollectionId
        /// </summary>
        public string TeamProjectCollectionId;

        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Equals(TfsGiggleWorkitem x, TfsGiggleWorkitem y)
        {
            Trace.TraceInformation("Equals called");
            return x.Id == y.Id && x.TeamProjectCollectionId == y.TeamProjectCollectionId;
        }

        /// <summary>
        /// Hashcode
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int GetHashCode(TfsGiggleWorkitem obj)
        {
            unchecked
            {
                Trace.TraceInformation("GetHashCode called");
                return obj.TeamProjectCollectionId.GetHashCode() * 31 + obj.Id.GetHashCode();
            }
        }

        /// <summary>
        /// Hashcode
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            unchecked
            {
                Trace.TraceInformation("GetHashCode called");
                return this.GetHashCode(this);
            }
        }

        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static bool operator ==(TfsGiggleWorkitem x, TfsGiggleWorkitem y)
        {
            Trace.TraceInformation("== called");
            return x.Equals(y);
        }

        /// <summary>
        /// Not equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static bool operator !=(TfsGiggleWorkitem x, TfsGiggleWorkitem y)
        {
            Trace.TraceInformation("!= called");
            return !x.Equals(y);
        }

        /// <summary>
        /// Equals again
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            Trace.TraceInformation("Equals called");
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            var tfsGiggleWorkitem = (TfsGiggleWorkitem)obj;
            if (tfsGiggleWorkitem.Id == Id && tfsGiggleWorkitem.TeamProjectCollectionId == TeamProjectCollectionId)
            {
                return true;
            }
            return false;
        }
    }

    /// <summary>
    /// File
    /// </summary>
    [Serializable]
    public struct TfsGiggleFile : IEqualityComparer<TfsGiggleFile>
    {
        /// <summary>
        /// Name
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Changesets
        /// </summary>
        public int NumberOfChangesets { get; set; }

        /// <summary>
        /// Workitems
        /// </summary>
        public int NumberOfWorkitems { get; set; }

        /// <summary>
        /// TeamProjectCollectionId
        /// </summary>
        public string TeamProjectCollectionId;

        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Equals(TfsGiggleFile x, TfsGiggleFile y)
        {
            Trace.TraceInformation("Equals called");
            return x.Name == y.Name && x.TeamProjectCollectionId == y.TeamProjectCollectionId;
        }

        /// <summary>
        /// Hashcode
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int GetHashCode(TfsGiggleFile obj)
        {
            unchecked
            {
                Trace.TraceInformation("GetHashCode called");
                return obj.TeamProjectCollectionId.GetHashCode() * 31 + obj.Name.GetHashCode();
            }
        }

        /// <summary>
        /// hashcode
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            unchecked
            {
                Trace.TraceInformation("GetHashCode called");
                return this.GetHashCode(this);
            }
        }

        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static bool operator ==(TfsGiggleFile x, TfsGiggleFile y)
        {
            Trace.TraceInformation("== called");
            return x.Equals(y);
        }

        /// <summary>
        /// Not equals
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static bool operator !=(TfsGiggleFile x, TfsGiggleFile y)
        {
            Trace.TraceInformation("!= called");
            return !x.Equals(y);
        }

        /// <summary>
        /// Equals again
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            Trace.TraceInformation("Equals called");
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            var tfsGiggleFile = (TfsGiggleFile)obj;
            if (tfsGiggleFile.Name == Name && tfsGiggleFile.TeamProjectCollectionId == TeamProjectCollectionId)
            {
                return true;
            }
            return false;
        }
    }


    /// <summary>
    /// Contains the result from a query
    /// </summary>
    [DataContract]
    public class QueryResultDTO
    {
        /// <summary>
        /// Distinct changesets found
        /// </summary>
        [DataMember]
        public TfsGiggleChangeset[] Changesets;

        /// <summary>
        /// Distinct workitems found
        /// </summary>
        [DataMember]
        public TfsGiggleWorkitem[] Workitems;

        /// <summary>
        /// Distinct files found
        /// </summary>
        [DataMember]
        public TfsGiggleFile[] Files;

        /// <summary>
        /// Time for creating the dto
        /// </summary>
        [DataMember]
        public long GetQueryResultDTOProcessingTimeInTicks;
    }
}